package com.adjaisd.scarecrow.service.impl;

import com.adjaisd.scarecrow.dto.QuotaTrend;
import com.adjaisd.scarecrow.entity.Board;
import com.adjaisd.scarecrow.entity.Device;
import com.adjaisd.scarecrow.entity.Quota;
import com.adjaisd.scarecrow.mapper.BoardMapper;
import com.adjaisd.scarecrow.repo.TimeSeriesRepository;
import com.adjaisd.scarecrow.service.BoardService;
import com.adjaisd.scarecrow.service.DeviceService;
import com.adjaisd.scarecrow.service.QuotaService;
import com.adjaisd.scarecrow.vo.BoardQuotaData;
import com.adjaisd.scarecrow.vo.BoardQuotaVO;
import com.adjaisd.scarecrow.vo.QuotaDataVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author adjaisd
 * @since 2022-04-28
 */
@Service
public class BoardServiceImpl extends ServiceImpl<BoardMapper, Board> implements BoardService {

    @Autowired
    BoardMapper boardMapper;

    @Override
    public List<Board> getAllBoard(Long userId) {
        QueryWrapper<Board> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Board::getUserId, userId)
                .gt(Board::getCreateDate, 0L);
        return this.list(wrapper);
    }

    @Override
    public Board getBoard(Long userId, String name, String quotaName, String unit) {
        QueryWrapper<Board> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Board::getUserId, userId)
                .eq(Board::getName, name)
                .eq(Board::getQuotaName, quotaName)
                .eq(Board::getUnit, unit);
        List<Board> boardList = this.list(wrapper);
        if (boardList.size() == 1) return boardList.get(0);
        else return null;
    }

    @Override
    public boolean addBoard(Board board) {
        return boardMapper.insert(board) > 0;
    }

    @Autowired
    DeviceService deviceService;

    @Autowired
    QuotaService quotaService;

    @Override
    public BoardQuotaVO getPreviewData(Long userId, String quotaName, String unit, String deviceIdList, String beg, String end, int type) {
        BoardQuotaVO boardQuotaVO = new BoardQuotaVO();
        boardQuotaVO.setQuotaName(quotaName);
        boardQuotaVO.setUnit(unit);

        List<String> timeList = null;
        List<BoardQuotaData> list = new LinkedList<>();
        for (String deviceId : deviceIdList.split(",")) {
            Device device = deviceService.getById(deviceId);
            if (device == null) continue;
            QueryWrapper<Quota> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Quota::getNumber, device.getNumber())
                    .eq(Quota::getName, quotaName)
                    .eq(Quota::getUnit, unit)
                    .eq(Quota::getOwnerId, userId)
                    .gt(Quota::getCreateTime, 0L);
            List<Quota> quotaList = quotaService.list(wrapper);
            for (Quota quota : quotaList) {
                Long quotaId = quota.getId();
                List<QuotaTrend> quotaTrendList = getQuotaTrendList(beg, end, quotaId + "", deviceId, type);
                timeList = quotaTrendList.stream().map(QuotaTrend::getTime).collect(Collectors.toList());
                List<Double> doubleList = quotaTrendList.stream().map(QuotaTrend::getPointValue).collect(Collectors.toList());
                boardQuotaVO.setXData(timeList);
                BoardQuotaData boardQuotaData = new BoardQuotaData(quotaId + "", quota.getWebhook(), deviceId, quota.getNumber()+"", quota.getReference(), doubleList);
                list.add(boardQuotaData);
            }
        }
        boardQuotaVO.setXData(timeList);
        boardQuotaVO.setSeries(list);
        return boardQuotaVO;
    }

    @Override
    public BoardQuotaVO getBoardData(String boardId, String beg, String end, int type) {
        Board board = getById(boardId);
        String deviceIdList = board.getDeviceIdList();
        BoardQuotaVO boardQuotaVO = new BoardQuotaVO();
        BeanUtils.copyProperties(board, boardQuotaVO);

        List<String> timeList = null;
        List<BoardQuotaData> list = new LinkedList<>();
        for (String deviceId : deviceIdList.split(",")) {
            Device device = deviceService.getById(deviceId);
            if (device == null) continue;
            QueryWrapper<Quota> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(Quota::getNumber, device.getNumber())
                    .eq(Quota::getName, board.getQuotaName())
                    .eq(Quota::getUnit, board.getUnit())
                    .eq(Quota::getOwnerId, board.getUserId())
                    .gt(Quota::getCreateTime, 0L);
            List<Quota> quotaList = quotaService.list(wrapper);
            for (Quota quota : quotaList) {
                Long quotaId = quota.getId();
                List<QuotaTrend> quotaTrendList = getQuotaTrendList(beg, end, quotaId + "", deviceId, type);
                timeList = quotaTrendList.stream().map(QuotaTrend::getTime).collect(Collectors.toList());
                List<Double> doubleList = quotaTrendList.stream().map(QuotaTrend::getPointValue).collect(Collectors.toList());
                boardQuotaVO.setXData(timeList);
                BoardQuotaData boardQuotaData = new BoardQuotaData(quotaId + "", quota.getWebhook(), deviceId, quota.getNumber()+"", quota.getReference(), doubleList);
                list.add(boardQuotaData);
            }
        }
        boardQuotaVO.setXData(timeList);
        boardQuotaVO.setSeries(list);
        return boardQuotaVO;
    }

    @Autowired
    TimeSeriesRepository timeSeriesRepository;

    public List<QuotaTrend> getQuotaTrendList(String beg, String end, String quotaId, String deviceId, int type) {
        StringBuilder ql = new StringBuilder("select first(value) as pointValue from quota ");
        ql.append("where time>='" + beg + "' and time<='" + end + "' ");
        ql.append("and quotaId='" + quotaId + "' ");
        ql.append("and deviceId='" + deviceId + "' ");
        // 时间间隔
        if (type == 1) // 1分钟
            ql.append("group by time(1m)");
        if (type == 2) // 1小时
            ql.append("group by time(1h)");
        if (type == 3) // 1天
            ql.append("group by time(1d)");
        List<QuotaTrend> quotaTrendList = timeSeriesRepository.query(ql.toString(), QuotaTrend.class);
        return fill(quotaTrendList);
    }

    // 填充数据
    private List<QuotaTrend> fill(List<QuotaTrend> quotaTrendList) {
        Double previousValue = null;// 上一个值
        for (QuotaTrend quotaTrend : quotaTrendList) {
            if (quotaTrend.getPointValue() != null) {
                previousValue = quotaTrend.getPointValue();
                break;
            }
        }
        if (previousValue == null) previousValue = 0d;
        //数据填充逻辑
        for (QuotaTrend quotaTrend : quotaTrendList) {
            if (quotaTrend.getPointValue() == null)
                quotaTrend.setPointValue(previousValue);
            else previousValue = quotaTrend.getPointValue();
        }
        return quotaTrendList;
    }


}
